/*
   Copyright (c) 2023 李伟国
   learner-platform is licensed under Mulan PSL v2.
   You can use this software according to the terms and conditions of the Mulan PSL v2. 
   You may obtain a copy of Mulan PSL v2 at:
               http://license.coscl.org.cn/MulanPSL2 
   THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.  
   See the Mulan PSL v2 for more details. 
*/

package cn.platform.service.impl;

import cn.platform.constant.ProblemConstant;
import cn.platform.constant.TestCaseConstant;
import cn.platform.dto.CodeRunMsg;
import cn.platform.dto.CodeRunResult;
import cn.platform.dto.TestInOut;
import cn.platform.dto.TestInOutDto;
import cn.platform.entity.CommitRecord;
import cn.platform.entity.Problem;
import cn.platform.entity.Runner;
import cn.platform.entity.TestCase;
import cn.platform.exception.CodeInfoIncompleteException;
import cn.platform.mapper.CommitRecordMapper;
import cn.platform.mapper.ProblemMapper;
import cn.platform.mapper.TestCaseMapper;
import cn.platform.page.PageFactory;
import cn.platform.service.IJudgeService;
import cn.platform.service.IProblemService;
import cn.platform.utils.CodeUtils;
import cn.platform.utils.UserUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.Date;

@Service
public class ProblemServiceImpl extends ServiceImpl<ProblemMapper, Problem> implements IProblemService, ProblemConstant {

    @Autowired
    private IJudgeService judgeService;

    @Autowired
    private CommitRecordMapper commitRecordMapper;

    @Autowired
    private TestCaseMapper testCaseMapper;

    /**
     * 保存题目信息，返回
     * @param problem 题目
     * @return 题目id
     */
    @Override
    public int saveDraft(Problem problem) {
        problem.setCreateTime(new Date());
        problem.setStatus(STATUS_DRAFT);
        int insert = this.baseMapper.insert(problem);
        if(insert == 0){
            return -1;
        }
        return problem.getId();
    }

    /**
     * 保存并发布题目
     *
     * @param problem 题目
     * @return 结果
     */
    @Override
    public int saveRelease(Problem problem) {
        problem.setCreateTime(new Date());
        problem.setStatus(STATUS_RELEASED);
        int insert = this.baseMapper.insert(problem);
        if(insert == 0){
            return -1;
        }
        return problem.getId();
    }

    /**
     * 保存用于判题的代码
     *
     * @param codeRunMsg 代码信息
     * @return 创建的id
     */
    @Override
    public Long saveTestCode(CodeRunMsg codeRunMsg) {
        if(ObjectUtils.isEmpty(codeRunMsg.getLang())){
            throw new CodeInfoIncompleteException("代码语言未确定");
        }
        if(ObjectUtils.isEmpty(codeRunMsg.getProblemId())){
            throw new CodeInfoIncompleteException("代码所属题目未确定");
        }
        if(ObjectUtils.isEmpty(codeRunMsg.getFilePrefix())
                ||ObjectUtils.isEmpty(codeRunMsg.getFileSuffix())){
            codeRunMsg.setFilePrefix(CodeUtils.filePrefix);
            codeRunMsg.setFileSuffix(CodeUtils.fileSuffix.get(codeRunMsg.getLang()));
        }
        judgeService.saveTestCode(codeRunMsg);
        CommitRecord commitRecord = new CommitRecord();
        commitRecord.setProblemId(codeRunMsg.getProblemId());
        commitRecord.setContent(codeRunMsg.getCode());
        commitRecord.setLang(codeRunMsg.getLang());
        commitRecord.setUserId(UserUtil.getUserId());
        commitRecordMapper.insert(commitRecord);
        return commitRecord.getId();
    }

    /**
     * 保存测试样例
     *
     * @param testInOutDto 测试样例
     * @return 是否保存成功
     */
    @Override
    public boolean saveTestCase(TestInOutDto testInOutDto) {
        System.out.println(testInOutDto.toString());
        judgeService.saveTestCase(testInOutDto.getProblemId(), testInOutDto.getTestInOuts());
        TestCase testCase = new TestCase();
        testCase.setType(TestCaseConstant.TYPE_CASE);
        testCase.setProblemId(testInOutDto.getProblemId());
        testCase.setMemoryLimit(testInOutDto.getMemoryLimit());
        testCase.setTimeLimit(testInOutDto.getTimeLimit());
        boolean r = true;
        for(TestInOut t : testInOutDto.getTestInOuts()){
            testCase.setInput(t.getInput());
            testCase.setOutput(t.getOutput());
            testCase.setRank(t.getRank());
            testCase.setTip(t.getTip());
            System.out.println(testCase);
            r &= testCaseMapper.insert(testCase)>0;
        }
        return r;
    }

    /**
     * 查询题目列表
     *
     * @param id    题目id
     * @param title 题目标题
     * @param label 标签
     * @return 列表
     */
    @Override
    public Page<Problem> getProblemByIdAndTitleAndLabels(Integer id, String title, String label) {
        return this.baseMapper.selectProblemByIdAndTitleAndLabels(PageFactory.defaultPage(), id, title, label);
    }

    /**
     * 保存测试样例
     *
     * @param testInOutDto 测试样例
     * @return 是否保存成功
     */
    @Override
    public boolean saveTestSample(TestInOutDto testInOutDto) {
        System.out.println(testInOutDto.toString());
        judgeService.saveTestSample(testInOutDto.getProblemId(), testInOutDto.getTestInOuts());
        TestCase testCase = new TestCase();
        testCase.setType(TestCaseConstant.TYPE_SAMPLE);
        testCase.setProblemId(testInOutDto.getProblemId());
        testCase.setMemoryLimit(testInOutDto.getMemoryLimit());
        testCase.setTimeLimit(testInOutDto.getTimeLimit());
        boolean r = true;
        for(TestInOut t : testInOutDto.getTestInOuts()){
            testCase.setInput(t.getInput());
            testCase.setOutput(t.getOutput());
            testCase.setRank(t.getRank());
            testCase.setTip(t.getTip());
            System.out.println(testCase);
            r &= testCaseMapper.insert(testCase)>0;
        }
        return r;
    }

    /**
     * 执行测试样例
     *
     * @param runner 题目运行条件
     * @return 运行结果
     */
    @Override
    public CodeRunResult runTestCode(Runner runner) {
        CodeRunResult codeRunResult = judgeService.runTestCode(runner);
        return codeRunResult;
    }

    /**
     * 测试代码判题
     *
     * @param userId 用户id
     * @param runner 题目运行条件
     * @return 运行结果
     */
    @Override
    public CodeRunResult runUserCode(Long userId, Runner runner) {
        return judgeService.runUserCode(userId, runner);
    }
}
